﻿using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ManaSky.Apollo;
using ManaSky.Common.Models;
using ManaSky.SSO.Models;

namespace ManaSky.SSO
{
    /// <summary>
    /// 自定义Jwt服务
    /// </summary>
    public static class JwtService
    {
        public static void AddJwtService(this IServiceCollection service)
        {
            var token = AppsettingsHelper.GetConfig<JwtConfig>("JwtTokens");
            service.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                .AddJwtBearer(options =>
                {
                    //options.RequireHttpsMetadata = false;
                    options.SaveToken = true;
                    options.TokenValidationParameters = new TokenValidationParameters()
                    {
                        ValidateIssuer = true, //是否验证Issuer
                        ValidateAudience = true, //是否验证Audience
                        ValidateIssuerSigningKey = true,//是否验证IssuerSigningKey
                        ValidateLifetime = true,//是否验证超时  当设置exp和nbf时有效 同时启用ClockSkew
                        ValidAudience = token.Audience, //Audience
                        ValidIssuer = token.Issuer, //Issuer,这个和前面签发jwt的设置一样
                        IssuerSigningKey = token.SymmetricSecurityKey,
                        ClockSkew = TimeSpan.FromSeconds(token.ClockSkewExpiration) //缓冲时间 默认5分钟
                    };
                    options.Events = new JwtBearerEvents
                    {
                        //此处为权限验证失败后触发的事件
                        OnChallenge = context =>
                        {
                            //此处代码为终止.Net Core默认的返回类型和数据结果，这个很重要哦，必须
                            context.HandleResponse();
                            //自定义自己想要返回的数据结果，我这里要返回的是Json对象，通过引用Newtonsoft.Json库进行转换
                            var payload = JsonConvert.SerializeObject(ApiRequest.LoginExpired("无权访问该接口！"));
                            //自定义返回的数据类型
                            context.Response.ContentType = "application/json;charset=utf-8";
                            //自定义返回状态码，默认为401 我这里改成 200
                            context.Response.StatusCode = StatusCodes.Status200OK;
                            //输出Json数据结果
                            context.Response.WriteAsync(payload);
                            return Task.FromResult(0);
                        }
                    };
                });
        }
    }
}
